package com.ibeeking.found.msg.rest.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ibeeking.found.common.base.BaseDO;
import com.ibeeking.found.common.config.prop.FileOssProp;
import com.ibeeking.found.common.enums.mp.WxMpSourceTypeEnum;
import com.ibeeking.found.common.utils.UrlUtils;
import com.ibeeking.found.common.utils.UserUtils;
import com.ibeeking.found.id.GenerateId;
import com.ibeeking.found.msg.api.common.dto.OssPolicyDto;
import com.ibeeking.found.msg.api.common.query.FileNameQuery;
import com.ibeeking.found.msg.api.feign.MsgFileFeignClient;
import com.ibeeking.found.msg.rest.config.prop.FileConfigProp;
import com.ibeeking.found.msg.rest.service.IWxMpSourceService;
import com.ibeeking.found.msg.rest.service.IOpenService;
import com.ibeeking.found.msg.service.common.bo.WxMpSourceBO;
import com.ibeeking.found.msg.service.common.bo.WxMpSourceDetailBO;
import com.ibeeking.found.msg.service.common.constants.RedisKeyConstant;
import com.ibeeking.found.msg.service.common.dos.WxMpSourceDO;
import com.ibeeking.found.msg.service.common.dos.WxMpSourceDetailDO;
import com.ibeeking.found.msg.service.common.param.WxMpSourceDetailParam;
import com.ibeeking.found.msg.service.common.param.WxMpSourceParam;
import com.ibeeking.found.msg.service.common.query.WxMpImageTextQuery;
import com.ibeeking.found.msg.service.common.query.WxMpSourcePageQuery;
import com.ibeeking.found.msg.service.common.vo.*;
import com.ibeeking.found.msg.service.mapper.WxMpSourceDetailMapper;
import com.ibeeking.found.msg.service.mapper.WxMpSourceMapper;
import com.ibeeking.nematos.constants.enums.LogClassifyEnum;
import com.ibeeking.nematos.core.utils.SpringBeanUtil;
import com.ibeeking.nematos.exception.BusinessException;
import com.ibeeking.nematos.log.utils.LogUtils;
import com.ibeeking.nematos.redis.annotation.CacheEvict;
import com.ibeeking.nematos.redis.annotation.CacheQuery;
import com.ibeeking.nematos.redis.utils.RedisUtils;
import com.ibeeking.nematos.utils.bean.BeanUtil;
import com.ibeeking.nematos.utils.data.Collections3;
import com.ibeeking.nematos.utils.data.DataUtils;
import com.ibeeking.nematos.utils.data.StringUtils;
import com.ibeeking.nematos.utils.file.FileUtils;
import com.ibeeking.nematos.utils.id.IdGenerator;
import com.ibeeking.nematos.utils.json.JsonUtils;
import com.ibeeking.nematos.utils.result.ResponseResult;
import lombok.SneakyThrows;
import me.chanjar.weixin.common.api.WxConsts;
import me.chanjar.weixin.common.bean.result.WxMediaUploadResult;
import me.chanjar.weixin.common.error.WxErrorException;
import me.chanjar.weixin.mp.api.WxMpMaterialService;
import me.chanjar.weixin.mp.api.WxMpService;
import me.chanjar.weixin.mp.bean.material.*;
import me.chanjar.weixin.mp.config.WxMpConfigStorage;
import me.chanjar.weixin.open.api.WxOpenMpService;
import org.springframework.http.HttpHeaders;
import org.springframework.http.HttpStatus;
import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @ClassName WxMpSourceServiceImpl
 * @Description
 * @Author ibeeking
 * @Date 2021-02-03 20:08
 **/
@Service
public class WxMpSourceServiceImpl extends ServiceImpl<WxMpSourceMapper, WxMpSourceDO> implements IWxMpSourceService {

    @Resource
    private IOpenService wxOpenServiceImpl;

    @Resource
    private WxMpSourceMapper wxMpSourceMapper;

    @Resource
    private WxMpSourceDetailMapper wxMpSourceDetailMapper;
    @Resource
    private RedisUtils redisUtils;

    @Resource
    private MsgFileFeignClient fileFeignClient;

    @Resource
    private FileOssProp fileOssProp;

    @Resource
    private FileConfigProp fileConfigProp;

    @Override
    public Page<WxMpSourcePageVO> pageList(WxMpSourcePageQuery query) {
        LambdaQueryWrapper<WxMpSourceDO> queryWrapper = new LambdaQueryWrapper<>(WxMpSourceDO.class)
                .eq(query.getAppId() != null, WxMpSourceDO::getAppId, query.getAppId())
                .eq(null != query.getAsyncStatus(), WxMpSourceDO::getAsyncStatus, query.getAsyncStatus())
                .eq(null != query.getGroupId(), WxMpSourceDO::getGroupId, query.getGroupId())
                .like(StringUtils.isNotBlank(query.getName()), WxMpSourceDO::getName, query.getName())
                .like(StringUtils.isNotBlank(query.getRemark()), WxMpSourceDO::getRemark, query.getRemark())
                .orderByDesc(BaseDO::getCreateTime);
        if (null != query.getSourceType()) {
            Integer sourceTypeId = WxMpSourceTypeEnum.getCodeByName(query.getSourceType());
            queryWrapper.eq(WxMpSourceDO::getSourceTypeId, sourceTypeId);
        }


        Page<WxMpSourceDO> wxMpSourceDOPages = wxMpSourceMapper.selectPage(new Page<>(query.getPageNum(), query.getPageSize()), queryWrapper);
        Page<WxMpSourcePageVO> wxMpSourceDOPageResult = BeanUtil.convertPage(wxMpSourceDOPages, WxMpSourcePageVO.class);

        List<WxMpSourcePageVO> wxMpSourcePageVOS = wxMpSourceDOPageResult.getRecords();
        if (!Collections3.isEmpty(wxMpSourcePageVOS)) {
            //查询图文素材明细
            List<Long> wxMpSourceIds = wxMpSourcePageVOS.parallelStream().map(WxMpSourcePageVO::getId).collect(Collectors.toList());
            List<WxMpSourceDetailDO> wxMpSourceDetailDos = wxMpSourceDetailMapper.selectList(new LambdaQueryWrapper<>(WxMpSourceDetailDO.class)
                    .orderByAsc(WxMpSourceDetailDO::getSort)
                    .orderByDesc(WxMpSourceDetailDO::getCreateTime)
                    .in(WxMpSourceDetailDO::getSourceId, wxMpSourceIds)
            );

            Map<Long, List<WxMpSourceDetailPageVO>> wxMpSourceDetailPageVOSMap = Collections3.emptyMap();
            Map<Long, String> wxMpSourcePathMap = Collections3.emptyMap();
            if (!Collections3.isEmpty(wxMpSourceDetailDos)) {
                List<WxMpSourceDetailPageVO> wxMpSourceDetailPageVOS = JsonUtils.jsonToList(wxMpSourceDetailDos, WxMpSourceDetailPageVO.class);
                //根据素材id分组
                wxMpSourceDetailPageVOSMap = wxMpSourceDetailPageVOS.stream().collect(Collectors.groupingBy(WxMpSourceDetailPageVO::getSourceId));
                List<Long> thumbMediaIds = wxMpSourceDetailPageVOS.parallelStream().map(WxMpSourceDetailPageVO::getThumbMediaId).collect(Collectors.toList());
                //查询素材
                List<WxMpSourceDO> wxMpSourceDOS = wxMpSourceMapper.selectList(new LambdaQueryWrapper<>(WxMpSourceDO.class).in(BaseDO::getId, thumbMediaIds));
                wxMpSourcePathMap = wxMpSourceDOS.parallelStream().collect(Collectors.toMap(BaseDO::getId, WxMpSourceDO::getPath, (s, a) -> a));
            }

            Map<Long, Integer> WxMpSourceTypeMap = wxMpSourceDOPages.getRecords().stream().collect(Collectors.toMap(BaseDO::getId, WxMpSourceDO::getSourceTypeId, (s, a) -> a));
            for (WxMpSourcePageVO wxMpSourcePageVO : wxMpSourcePageVOS) {
                if (!CollectionUtils.isEmpty(wxMpSourceDetailPageVOSMap)) {
                    List<WxMpSourceDetailPageVO> wxMpSourceDetailPageVOS = wxMpSourceDetailPageVOSMap.get(wxMpSourcePageVO.getId());
                    Map<Long, String> wxMpSourceOssPathMap = wxMpSourcePathMap;
                    if (!Collections3.isEmpty(wxMpSourceDetailPageVOS)) {
                        wxMpSourceDetailPageVOS.stream().filter(a -> null != wxMpSourceOssPathMap.get(a.getThumbMediaId())).forEach(mpSourceNewsPageVO -> {
                            mpSourceNewsPageVO.setThumbMediaUrl(fileOssProp.getHost().concat(wxMpSourceOssPathMap.get(mpSourceNewsPageVO.getThumbMediaId())));
                        });
                    }
                    wxMpSourcePageVO.setSourceDetail(wxMpSourceDetailPageVOS);
                }

                if (StringUtils.isNotBlank(wxMpSourcePageVO.getPath())) {
                    wxMpSourcePageVO.setPath(fileOssProp.getHost().concat(wxMpSourcePageVO.getPath()));
                }
                if (null != WxMpSourceTypeMap.get(wxMpSourcePageVO.getId())) {
                    wxMpSourcePageVO.setSourceType(WxMpSourceTypeEnum.getNameByCode(WxMpSourceTypeMap.get(wxMpSourcePageVO.getId())));
                }
            }
        }

        return wxMpSourceDOPageResult;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public String add(WxMpSourceParam param) {
        Long userId = UserUtils.getUserId();
        WxMpSourceDO wxMpSourceDO = BeanUtil.convertBean(param, WxMpSourceDO.class);
        wxMpSourceDO.setSourceTypeId(WxMpSourceTypeEnum.getCodeByName(param.getSourceType()));
        wxMpSourceDO.setCreateBy(userId);
        wxMpSourceDO.setCreateTime(LocalDateTime.now());
        wxMpSourceDO.setModifyTime(LocalDateTime.now());
        wxMpSourceDO.setId(GenerateId.generateId());
        if (!Collections3.isEmpty(param.getSourceDetail())) {
            List<WxMpSourceDetailDO> wxMpSourceDetailDOS = JsonUtils.jsonToList(param.getSourceDetail(), WxMpSourceDetailDO.class);
            wxMpSourceDetailDOS.stream().forEach(a -> {
                a.setSourceId(wxMpSourceDO.getId());
                a.setCreateTime(LocalDateTime.now());
            });
            wxMpSourceDetailMapper.insertBatchSomeColumn(wxMpSourceDetailDOS);
            if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equalsIgnoreCase(param.getSourceType())) {
                //图文消息title作为name
                wxMpSourceDO.setName(wxMpSourceDetailDOS.get(0).getTitle());
            }
        }
        wxMpSourceMapper.insert(wxMpSourceDO);
        return String.valueOf(wxMpSourceDO.getId());
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheName = RedisKeyConstant.MP_SOURCE, key = "#param.id")
    @Override
    public Boolean modify(WxMpSourceParam param) {
        Long userId = UserUtils.getUserId();
        if (Collections3.isEmpty(param.getSourceDetail())) {
            throw new BusinessException("永久图文素材必填");
        }

        WxMpSourceDO wxMpSourceDO = BeanUtil.convertBean(param, WxMpSourceDO.class);
        wxMpSourceDO.setSourceTypeId(WxMpSourceTypeEnum.getCodeByName(param.getSourceType()));
        wxMpSourceDO.setModifyBy(userId);
        wxMpSourceDO.setModifyTime(LocalDateTime.now());
        WxMpSourceBO query = getBean().querySourceById(param.getId());
        if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equalsIgnoreCase(param.getSourceType())) {
            wxMpSourceDO.setAsyncStatus(0);
            if (1 == query.getAsyncStatus()) {
                wxMpSourceDO.setModifyStatus(1);
            }
            //图文消息title作为name
            wxMpSourceDO.setName(param.getSourceDetail().get(0).getTitle());
        }
        wxMpSourceMapper.updateById(wxMpSourceDO);

        if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equalsIgnoreCase(param.getSourceType())) {
            List<WxMpSourceDetailDO> wxMpSourceDetailDos = wxMpSourceDetailMapper.selectList(new LambdaQueryWrapper<>(WxMpSourceDetailDO.class).eq(WxMpSourceDetailDO::getSourceId, param.getId()));
            List<Long> oldSourceDetailIds = wxMpSourceDetailDos.parallelStream().map(WxMpSourceDetailDO::getId).collect(Collectors.toList());
            List<Long> newSourceDetailIds = param.getSourceDetail().stream().filter(a -> null != a.getId()).map(WxMpSourceDetailParam::getId).collect(Collectors.toList());

            // 2。 进行取差集
            List<Long> del = Collections3.difference(oldSourceDetailIds, newSourceDetailIds);
            if (1 == query.getAsyncStatus()) {
                if (!Collections3.isEmpty(del) || (oldSourceDetailIds.size() != newSourceDetailIds.size())) {
                    throw new BusinessException("图文素材已发布，禁止增删");
                }
            }
            wxMpSourceDetailMapper.delete(new LambdaQueryWrapper<>(WxMpSourceDetailDO.class).eq(WxMpSourceDetailDO::getSourceId, param.getId()));
            List<WxMpSourceDetailDO> add = JsonUtils.jsonToList(param.getSourceDetail(), WxMpSourceDetailDO.class);
            add.stream().forEach(a -> {
                a.setSourceId(wxMpSourceDO.getId());
                a.setCreateTime(LocalDateTime.now());
            });
            wxMpSourceDetailMapper.insertBatchSomeColumn(add);
        }
        return true;
    }


    @Override
    public Boolean publishMediaSource(Long sourceId) {
        WxMpSourceBO wxMpSourceBO = getBean().querySourceById(sourceId);
        if (1 == wxMpSourceBO.getAsyncStatus()) {
            throw new BusinessException("不要重复发布");
        }
        getBean().uploadMediaToWx(sourceId);
        return true;
    }

    @Override
    public WxMpSourceVO view(Long id) {
        WxMpSourceBO wxMpSourceBO = getBean().querySourceById(id);
        if (wxMpSourceBO == null) {
            return null;
        }
        WxMpSourceVO wxMpSourceVO = BeanUtil.convertBean(wxMpSourceBO, WxMpSourceVO.class);
        if (StringUtils.isNotBlank(wxMpSourceVO.getPath())) {
            wxMpSourceVO.setPath(fileOssProp.getHost().concat(wxMpSourceVO.getPath()));
        }
        List<WxMpSourceDetailVO> wxMpSourceDetailVos = JsonUtils.jsonToList(wxMpSourceBO.getSourceDetail(), WxMpSourceDetailVO.class);

        if (!Collections3.isEmpty(wxMpSourceDetailVos)) {
            wxMpSourceDetailVos.stream().forEach(wxMpSourceDetailVO -> {
                WxMpSourceBO wxMpSourceBO1 = getBean().querySourceById(wxMpSourceDetailVO.getThumbMediaId());
                if (wxMpSourceBO1 != null) {
                    if (StringUtils.isNotBlank(wxMpSourceBO1.getPath())) {
                        wxMpSourceDetailVO.setThumbMediaUrl(fileOssProp.getHost().concat(wxMpSourceBO1.getPath()));
                    }
                } else {
                    LogUtils.warn("素材详情thumbMedia查询为空,thumbMediaId:[{}]", wxMpSourceDetailVO.getThumbMediaId());
                }
            });
            wxMpSourceVO.setSourceDetail(wxMpSourceDetailVos);
        }
        return wxMpSourceVO;
    }

    @Override
    public WxMpSourceVO queryByMediaId(String mediaId){
        WxMpSourceDO wxMpSourceDO = wxMpSourceMapper.selectOne(new LambdaQueryWrapper<WxMpSourceDO>().eq(WxMpSourceDO::getMediaId, mediaId));
        if (wxMpSourceDO == null) {
            return null;
        }
        WxMpSourceVO wxMpSourceVO = BeanUtil.convertBean(wxMpSourceDO, WxMpSourceVO.class);
        if (StringUtils.isNotBlank(wxMpSourceDO.getPath())) {
            wxMpSourceVO.setPath(fileOssProp.getHost().concat(wxMpSourceDO.getPath()));
        }
        List<WxMpSourceDetailVO> wxMpSourceDetailVos = JsonUtils.jsonToList(wxMpSourceVO.getSourceDetail(), WxMpSourceDetailVO.class);

        if (!Collections3.isEmpty(wxMpSourceDetailVos)) {
            wxMpSourceDetailVos.stream().forEach(wxMpSourceDetailBO -> {
                WxMpSourceBO wxMpSourceBO1 = getBean().querySourceById(wxMpSourceDetailBO.getThumbMediaId());
                if (wxMpSourceBO1 != null) {
                    if (StringUtils.isNotBlank(wxMpSourceBO1.getPath())) {
                        wxMpSourceDetailBO.setThumbMediaUrl(fileOssProp.getHost().concat(wxMpSourceBO1.getPath()));
                    }
                } else {
                    LogUtils.warn("素材详情thumbMedia查询为空,thumbMediaId:[{}]", wxMpSourceDetailBO.getThumbMediaId());
                }
            });
            wxMpSourceVO.setSourceDetail(wxMpSourceDetailVos);
        }
        return wxMpSourceVO;
    }


    @CacheQuery(cacheName = RedisKeyConstant.MP_SOURCE, key = "#id", expires = RedisKeyConstant.MONTH)
    @Override
    public WxMpSourceBO querySourceById(Long sourceId) {
        WxMpSourceDO wxMpSourceDO = wxMpSourceMapper.selectById(sourceId);
        if (null == wxMpSourceDO) {
            return null;
        }
        WxMpSourceBO wxMpSourceBO = BeanUtil.convertBean(wxMpSourceDO, WxMpSourceBO.class);
        if (null != wxMpSourceDO.getSourceTypeId()) {
            wxMpSourceBO.setSourceType(WxMpSourceTypeEnum.getNameByCode(wxMpSourceDO.getSourceTypeId()));
        }

        if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {
            List<WxMpSourceDetailDO> wxMpSourceDetailDos = wxMpSourceDetailMapper.selectList(new LambdaQueryWrapper<>(WxMpSourceDetailDO.class).eq(WxMpSourceDetailDO::getSourceId, sourceId));
            List<WxMpSourceDetailBO> wxMpSourceDetailBos = JsonUtils.jsonToList(wxMpSourceDetailDos, WxMpSourceDetailBO.class);
            wxMpSourceBO.setSourceDetail(wxMpSourceDetailBos);
        }

        return wxMpSourceBO;
    }

    @Override
    public WxMpSourceSimpleVO sourceSimpleDtoView(Long id) {
        WxMpSourceVO wxMpSourceVO = getBean().view(id);
        if (wxMpSourceVO == null) {
            return null;
        }
        WxMpSourceSimpleVO vo = new WxMpSourceSimpleVO();
        vo.setId(id);
        vo.setName(wxMpSourceVO.getName());
        String path = wxMpSourceVO.getPath();
        if (StringUtils.isNotBlank(path)) {
            vo.setMediaUrl(path);
        } else {
            List<WxMpSourceDetailVO> params = wxMpSourceVO.getSourceDetail();
            if (Collections3.isNotEmpty(params)) {
                vo.setMediaUrl(params.get(0).getThumbMediaUrl());
            }
        }
        return vo;
    }

    @Transactional(rollbackFor = Exception.class)
    @CacheEvict(cacheName = RedisKeyConstant.MP_SOURCE, key = "#id")
    @Override
    public Boolean delRemoteAndLocalSource(Long sourceId, Integer type) {
        //删除素材库
        WxMpSourceBO wxMpSourceBO = getBean().querySourceById(sourceId);
        Long tenantId = UserUtils.getTenantID();
        if (1 == wxMpSourceBO.getAsyncStatus()) {
            try {
                WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
                if(wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
                WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
                if(wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");

                wxMpMaterialService.materialDelete(wxMpSourceBO.getMediaId());
                WxMpSourceDO wxMpSourceDO = wxMpSourceMapper.selectById(sourceId);
                if(wxMpSourceDO == null) throw new BusinessException("没有查询到需要修改的记录!");
                wxMpSourceDO.setAsyncStatus(0);
                wxMpSourceMapper.updateById(wxMpSourceDO);
            } catch (WxErrorException e) {
                LogUtils.error(LogClassifyEnum.ERROR_LOG, "删除永久素材失败:[{}]", sourceId, e.getMessage());
                throw new BusinessException(e.getError().getErrorMsg(), e);
            }
        }

        if (1 == type) {
            wxMpSourceMapper.deleteById(sourceId);
        }
        return true;
    }

    @Override
    public String uploadMediaToWx(Long sourceId) {
        WxMpSourceBO wxMpSourceBO = getBean().querySourceById(sourceId);
        Long tenantId = UserUtils.getTenantID();
        if (0 == wxMpSourceBO.getAsyncStatus()) {
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if(wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
            if(wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");

            String mediaType = "";
            String localFileFullPath = "";
            //上传到素材库
            //下载临时文件
            WxMpMaterial wxMpMaterial = new WxMpMaterial();
            WxMpMaterialNews wxMpMaterialNews =  new WxMpMaterialNews();
            List<WxMpMaterialArticleUpdate> WxMpMaterialArticleUpdateNews = new ArrayList<>();
            if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equals(wxMpSourceBO.getSourceType())) {
                List<WxMpSourceDetailDO> wxMpSourceDetailDos = wxMpSourceDetailMapper.selectList(new LambdaQueryWrapper<>(WxMpSourceDetailDO.class).eq(WxMpSourceDetailDO::getSourceId, sourceId));
                if (1 == wxMpSourceBO.getModifyStatus()) {
                    for (WxMpSourceDetailDO wxMpSourceDetailDO : wxMpSourceDetailDos) {
                        WxMpMaterialArticleUpdate updateNew = new WxMpMaterialArticleUpdate();
                        updateNew.setIndex(wxMpSourceDetailDO.getSort());
                        updateNew.setMediaId(wxMpSourceBO.getMediaId());
                        WxMpNewsArticle wxMpNewsArticle = new WxMpNewsArticle();
                        wxMpNewsArticle.setThumbMediaId(getBean().uploadMediaToWx(wxMpSourceDetailDO.getThumbMediaId()));
                        wxMpNewsArticle.setAuthor(wxMpSourceDetailDO.getAuthor());
                        wxMpNewsArticle.setTitle(wxMpSourceDetailDO.getTitle());
                        wxMpNewsArticle.setContentSourceUrl(wxMpSourceDetailDO.getContentSourceUrl());
                        wxMpNewsArticle.setContent(wxMpSourceDetailDO.getContent());
                        wxMpNewsArticle.setDigest(wxMpSourceDetailDO.getDigest());
                        wxMpNewsArticle.setShowCoverPic(1 == wxMpSourceDetailDO.getShowCoverPic());
                        wxMpNewsArticle.setUrl(wxMpSourceDetailDO.getContentSourceUrl());
                        wxMpNewsArticle.setNeedOpenComment(1 == wxMpSourceDetailDO.getNeedOpenComment());
                        wxMpNewsArticle.setOnlyFansCanComment(1 == wxMpSourceDetailDO.getOnlyFansCanComment());
                        updateNew.setArticles(wxMpNewsArticle);
                        WxMpMaterialArticleUpdateNews.add(updateNew);
                    }
                } else {
                    List<WxMpNewsArticle> articles = new ArrayList<>();
                    wxMpSourceDetailDos.stream().forEach(wxMpSourceDetailDO -> {
                        WxMpNewsArticle wxMpNewsArticle = new WxMpNewsArticle();
                        wxMpNewsArticle.setThumbMediaId(getBean().uploadMediaToWx(wxMpSourceDetailDO.getThumbMediaId()));
                        wxMpNewsArticle.setAuthor(wxMpSourceDetailDO.getAuthor());
                        wxMpNewsArticle.setTitle(wxMpSourceDetailDO.getTitle());
                        wxMpNewsArticle.setContentSourceUrl(wxMpSourceDetailDO.getContentSourceUrl());
                        wxMpNewsArticle.setContent(wxMpSourceDetailDO.getContent());
                        wxMpNewsArticle.setDigest(wxMpSourceDetailDO.getDigest());
                        wxMpNewsArticle.setShowCoverPic(1 == wxMpSourceDetailDO.getShowCoverPic());
                        wxMpNewsArticle.setUrl(wxMpSourceDetailDO.getContentSourceUrl());
                        wxMpNewsArticle.setNeedOpenComment(1 == wxMpSourceDetailDO.getNeedOpenComment());
                        wxMpNewsArticle.setOnlyFansCanComment(1 == wxMpSourceDetailDO.getOnlyFansCanComment());
                        articles.add(wxMpNewsArticle);
                    });
                    wxMpMaterialNews.setArticles(articles);
                }
            } else {

                localFileFullPath = downLoadFileToLocal(wxMpSourceBO.getPath());
                File uploadFileFullPath = new File(localFileFullPath);
                wxMpMaterial.setFile(uploadFileFullPath);
                wxMpMaterial.setName(wxMpSourceBO.getName());
                wxMpMaterial.setVideoTitle(wxMpSourceBO.getName());
                wxMpMaterial.setVideoIntroduction(wxMpSourceBO.getRemark());
            }

            if (WxMpSourceTypeEnum.PIC.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {
                //图片
                mediaType = WxConsts.MaterialType.IMAGE;
            } else if (WxMpSourceTypeEnum.VOICE.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {
                //语音
                mediaType = WxConsts.MaterialType.VOICE;
            } else if (WxMpSourceTypeEnum.VIDEO.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {
                //视频
                mediaType = WxConsts.MaterialType.VIDEO;
                wxMpMaterial.setVideoTitle(wxMpSourceBO.getName());
                wxMpMaterial.setVideoIntroduction(wxMpSourceBO.getRemark());
            } else if (WxMpSourceTypeEnum.MUSIC.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {
                //音乐
                mediaType = WxConsts.MaterialType.VOICE;
            } else if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {

            }
            try {
                WxMpMaterialUploadResult wxMpMaterialUploadResult = null;
                if (WxMpSourceTypeEnum.IMAGE_TEXT.getName().equalsIgnoreCase(wxMpSourceBO.getSourceType())) {
                    if (1 == wxMpSourceBO.getModifyStatus()) {
                        for (WxMpMaterialArticleUpdate update : WxMpMaterialArticleUpdateNews) {
                            wxMpMaterialService.materialNewsUpdate(update);
                        }
                    } else {
                        wxMpMaterialUploadResult = wxMpMaterialService.materialNewsUpload(wxMpMaterialNews);
                    }
                } else {
                    wxMpMaterialUploadResult = wxMpMaterialService.materialFileUpload(mediaType, wxMpMaterial);
                }

                if (StringUtils.isNotBlank(wxMpMaterialUploadResult.getMediaId())) {
                    //异步修改素材信息+删除临时文件
                    asyncModifyLocalSource(sourceId, wxMpMaterialUploadResult.getMediaId(), wxMpMaterialUploadResult.getUrl(), localFileFullPath);
                    return wxMpMaterialUploadResult.getMediaId();
                }
                throw new BusinessException(wxMpMaterialUploadResult.getErrMsg());
            } catch (WxErrorException e) {
                LogUtils.error(LogClassifyEnum.ERROR_LOG, "新增永久素材失败：[{}],[{}]", wxMpSourceBO.getId(), e.getMessage());
                throw new BusinessException(e.getError().getErrorMsg());
            }
        } else {
            return wxMpSourceBO.getMediaId();
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @SneakyThrows
    @Override
    public Integer syncPicSourceFromWx(String type) {
        try {
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if (wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpConfigStorage WxMpConfigStorage = wxOpenMpService.getWxMpConfigStorage();
            if (WxMpConfigStorage == null) {
                throw new BusinessException("无法获取公众号信息，请检查是否绑定公众号！");
            }
            String appId = WxMpConfigStorage.getAppId();
            WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
            if (wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialCountResult wxMpMaterialCountResult = wxMpMaterialService.materialCount();

            if (wxMpMaterialCountResult != null) {
                Integer imageCount = wxMpMaterialCountResult.getImageCount();
                BigDecimal bigImgGroups = DataUtils.divide(new BigDecimal(imageCount),new BigDecimal(18), 3);
                int imgGroups = bigImgGroups.intValue();
                int offGroups = imageCount - imgGroups * 18;

                List<WxMpSourceDO> wxMpSourceDOS = new ArrayList<>();
                List<WxMpMaterialFileBatchGetResult> WxMpMaterialFileBatchGetResults = new ArrayList<>();
                if(imgGroups == 0){
                    WxMpMaterialFileBatchGetResult WxMpMaterialFileBatchGetResult = wxMpMaterialService.materialFileBatchGet(WxConsts.MaterialType.IMAGE, 0, offGroups);
                    WxMpMaterialFileBatchGetResults.add(WxMpMaterialFileBatchGetResult);
                }else{
                    for(int i =0; i< imgGroups; i++){
                        WxMpMaterialFileBatchGetResult WxMpMaterialFileBatchGetResult = wxMpMaterialService.materialFileBatchGet(WxConsts.MaterialType.IMAGE, i * 18, 18);
                        WxMpMaterialFileBatchGetResults.add(WxMpMaterialFileBatchGetResult);
                    }
                    if(offGroups != 0){
                        WxMpMaterialFileBatchGetResult WxMpMaterialFileBatchGetResult = wxMpMaterialService.materialFileBatchGet(WxConsts.MaterialType.IMAGE, imgGroups * 18, offGroups);
                        WxMpMaterialFileBatchGetResults.add(WxMpMaterialFileBatchGetResult);
                    }
                }

                if(WxMpMaterialFileBatchGetResults.size() > 0) {
                    OssPolicyDto  ossPolicyDto = getOssFilePolicy();

                    WxMpMaterialFileBatchGetResults.stream().forEach(f->{
                        if (f != null && f.getItemCount() > 0) {
                            List<WxMpMaterialFileBatchGetResult.WxMaterialFileBatchGetNewsItem> wxMaterialFileBatchGetNewsItem = f.getItems();
                            wxMaterialFileBatchGetNewsItem.stream().forEach(d -> {
                                WxMpSourceDO wxMpSourceDO = new WxMpSourceDO();
                                wxMpSourceDO.setId(IdGenerator.getId());
                                wxMpSourceDO.setAppId(appId);
                                wxMpSourceDO.setGroupId(null);
                                wxMpSourceDO.setSourceTypeId(WxMpSourceTypeEnum.PIC.getCode());
                                wxMpSourceDO.setSourceType(WxMpSourceTypeEnum.PIC.getName());
                                wxMpSourceDO.setMediaId(d.getMediaId());
                                wxMpSourceDO.setMediaUrl(d.getUrl());
                                try {
                                    String fileName = (String.valueOf(System.currentTimeMillis())).concat("_".concat(d.getName()));
                                    String fileTag = ossPolicyDto.getDir() + fileName;
                                    MultipartFile multipartFile = FileUtils.getMultipartFile(d.getUrl(), fileName, fileTag);

                                    ResponseResult<String> responseResult = fileFeignClient.uploadFile(multipartFile);
                                    String fileUploadPath = responseResult.getData();
                                    wxMpSourceDO.setPath(UrlUtils.removeUrlDomainName(fileUploadPath));
                                } catch (Exception ex) {
                                    throw new BusinessException(ex.toString());
                                }
                                wxMpSourceDO.setName(d.getName());
                                wxMpSourceDO.setAsyncStatus(1);
                                wxMpSourceDO.setModifyStatus(0);
                                wxMpSourceDO.setCreateBy(UserUtils.getUserId());
                                wxMpSourceDO.setCreateTime(LocalDateTime.now());
                                wxMpSourceDO.setModifyTime(LocalDateTime.now());
                                wxMpSourceDOS.add(wxMpSourceDO);
                            });
                        }
                    });
                }

                if(wxMpSourceDOS.size() > 0){
                    return wxMpSourceMapper.insertBatchSomeColumn(wxMpSourceDOS);
                }else{
                    return 0;
                }
            }
        }catch(Exception ex){
            throw new BusinessException("同步素材异常");
        }
        return 0;
    }

    @Override
    public String uploadImageTextMediaToWx(WxMpImageTextQuery query) {
        Long tenantId = UserUtils.getTenantID();
        WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
        if(wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
        WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
        if(wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");

        String localPath = downLoadFileToLocal(query.getPath());
        File upload = new File(localPath);
        try {
            WxMediaImgUploadResult result = wxMpMaterialService.mediaImgUpload(upload);
            return result.getUrl();
        } catch (WxErrorException e) {
            LogUtils.error(LogClassifyEnum.ERROR_LOG, "新增图文素材内图片失败：[{}]", JsonUtils.toJsonStr(query), e);
            throw new BusinessException(e.getError().getErrorMsg(), e);
        }
    }

    @Override
    public String getVedioMediaSourceUrl(String mediaId){
        try {
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if(wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
            if(wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");

            WxMpMaterialVideoInfoResult result = wxMpMaterialService.materialVideoInfo(mediaId);
            return result.getDownUrl();
        } catch (WxErrorException e) {
            throw new BusinessException(e.getError().getErrorMsg(), e);
        }

    }

    @Override
    public ResponseEntity<byte[]> downloadPublishedVideoSource(String mediaId, String fileName){
        try {
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if(wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
            if(wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");
            InputStream is = wxMpMaterialService.materialImageOrVoiceDownload(mediaId);
            byte[] body = new byte[is.available()];
            is.read(body);
            HttpHeaders headers = new HttpHeaders();
            //设置文件类型
            headers.add("Content-Disposition", "attchement;filename=" +  URLEncoder.encode(fileName, "UTF-8"));
            headers.add("Content-Type", "application/octet-stream");
            HttpStatus statusCode = HttpStatus.OK;
            //返回数据
            ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
            return entity;

        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }

    @Override
    public ResponseEntity<byte[]> downloadDraftVideoSource(String mediaId, String fileName){
        try {
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if(wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
            if(wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");
            InputStream is = new FileInputStream(wxMpMaterialService.mediaDownload(mediaId));
            byte[] body = new byte[is.available()];
            is.read(body);
            HttpHeaders headers = new HttpHeaders();
            //设置文件类型
            headers.add("Content-Disposition", "attchement;filename=" +  URLEncoder.encode(fileName, "UTF-8"));
            headers.add("Content-Type", "application/octet-stream");
            HttpStatus statusCode = HttpStatus.OK;
            //返回数据
            ResponseEntity<byte[]> entity = new ResponseEntity<byte[]>(body, headers, statusCode);
            return entity;

        } catch (Exception e) {
            throw new BusinessException(e.getMessage(), e);
        }
    }
    @Override
    public WxMediaUploadResult getTempMedia(Long sourceId, String type, String appId) {
        WxMpSourceBO bo = this.querySourceById(sourceId);
        WxMediaUploadResult result = new WxMediaUploadResult();
        if (bo == null) {
            return result;
        }
        if (StringUtils.isBlank(bo.getPath())) {
            return result;
        }
        String path = downLoadFileToLocal(bo.getPath());

        File file = new File(path);
        Long tenantId = UserUtils.getTenantID();
        WxMpService wxMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
        try {
            if (false/*WxConsts.MediaFileType.THUMB.equals(type)*/) {
                //result = wxMpService.getMaterialService().mediaImgUpload(file);
            } else {
                result = wxMpService.getMaterialService().mediaUpload(type, file);
            }
            return result;
        } catch (Exception e) {
            log.error("微信接口调用失败:{}", e);
        } finally {
            file.delete();
            file = null;
        }

        return result;
    }

    private Integer  asyncModifyLocalSource(Long sourceId, String mediaId, String url, String localPath) {
        WxMpSourceDO wxMpSourceDO = wxMpSourceMapper.selectById(sourceId);
        if(wxMpSourceDO == null) throw new BusinessException("没有查询到需要修改的记录!");
        wxMpSourceDO.setMediaId(mediaId);
        wxMpSourceDO.setAsyncStatus(1);
        wxMpSourceDO.setMediaUrl(url);
        int updatedRows = wxMpSourceMapper.updateById(wxMpSourceDO);
        redisUtils.del(RedisKeyConstant.MP_SOURCE + sourceId);
        if (StringUtils.isNotBlank(localPath)) {
            try {
                FileUtils.delete(localPath);
            } catch (Exception e) {
                LogUtils.error(LogClassifyEnum.ERROR_LOG, "删除临时文件失败：[{}],[{}]", localPath, e.getMessage());
            }
        }
        return updatedRows;
    }

    private WxMediaUploadResult getSourceByMediaIdFromWx(String mediaId){
        try {
            Long tenantId = UserUtils.getTenantID();
            WxOpenMpService wxOpenMpService = wxOpenServiceImpl.getWxOpenMpService(tenantId);
            if (wxOpenMpService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialService wxMpMaterialService = wxOpenMpService.getMaterialService();
            if (wxMpMaterialService == null) throw new BusinessException("没有授权公众号，请先授权！");
            WxMpMaterialVideoInfoResult wxMpMaterialVideoInfoResult = wxMpMaterialService.materialVideoInfo(mediaId);
            return null;
        }catch(Exception ex){
            return null;
        }
    }
    private String downLoadFileToLocal(String fileName) {
        FileNameQuery fileNameQuery = new FileNameQuery();
        fileNameQuery.setFileName(fileName);
        fileNameQuery.setPath(fileConfigProp.getFilePath());

        ResponseResult<String> responseResult = fileFeignClient.downloadFile(fileNameQuery);
        if (null == responseResult || null == responseResult.getData()) {
            return "";
        }
        LogUtils.info("下载文件{}到本地{}",fileName, responseResult.getData());
        return responseResult.getData();

    }

    private OssPolicyDto getOssFilePolicy(){
        ResponseResult<OssPolicyDto> responseResult = fileFeignClient.policy();
        return responseResult.getData();
    }

    private IWxMpSourceService getBean() {
        return SpringBeanUtil.getBean(IWxMpSourceService.class);
    }

}
